﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Com.FirstSolver.Splash;
using Ioacp.Library.Helpers;
using Mina.Core.Session;
using Mina.Filter.Codec;
using Mina.Transport.Socket;

namespace Ioacp.Hanvon
{
    /// <summary>
    /// 汉王 - 人证核验终端
    /// 型号: M0816
    /// </summary>
    public class HanvonSDK
    {
        private AsyncSocketAcceptor TcpServer = null;

        private SM2UserInformation SM2ServerInfo = new SM2UserInformation(
    "Com.FirstSolver.Splash",
    "6B9C908A57EF9DB9B60E8660B94E5AFF748338B757428E26ABA5E6AE836F7E2F",
    "D6295D01B644F1C25C705BD23E498694A790A7E758C72B7378FD5C92D3690E21",
    "7410DFF1F16FAF12A7AE77CECADB788CD1E6BF35F666B92EF3301CC142216F8D"
);

        private bool IsServerRunning = false;       // 服务器是否已运行
        private ushort _tcpPort = 9910;                // 服务端端口号
        private ushort _udpPort = 9911;             // Udp 端口

        // 人证识别事件
        public event EventHandler<HanvonRecivedEventArgs> OnFaceCardDetectionChanged;

        // Session 会话打开
        private event EventHandler<dynamic> OnSessionOpened;

        public event EventHandler<dynamic> OnExecSync;

        public IoSession Session { get; set; }

        /// <summary>
        /// 最后一次收到数据的时间
        /// </summary>
        public DateTime LastRecTime { get; set; }

        #region Init

        /// <summary>
        /// 服务端端口号
        /// </summary>
        /// <param name="port"></param>
        public void Init(HanvonInitEventArgs e)
        {
            _tcpPort = e.TcpServerPort;
            _udpPort = (ushort)(_tcpPort + 1);
        }

        #endregion

        #region SessionOpened

        /// <summary>
        /// 会话打开
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TcpServer_SessionOpened(object sender, IoSessionEventArgs e)
        {
            Session = e.Session;

            FaceReaderProtocolCodecFactory.EnablePassiveEncryption(e.Session, true, SM2ServerInfo);

            LogEx.Debug(string.Format("汉王客户端上线 {0}", e.Session.RemoteEndPoint.ToString()));

            OnSessionOpened?.Invoke(this, e);
        }

        #endregion

        #region ExceptionCaught

        /// <summary>
        /// 异常消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TcpServer_ExceptionCaught(object sender, IoSessionExceptionEventArgs e)
        {
            // 异常, 关闭 Session
            e.Session.Close(true);
        }

        #endregion

        #region MessageReceived

        /// <summary>
        /// 接收到消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TcpServer_MessageReceived(object sender, IoSessionMessageEventArgs e)
        {
            try
            {
                LastRecTime = DateTime.Now;

                // 显示接收字符串
                string Message = (string)e.Message;

                COMMAND_PCIR_TYPE A = Message.FromJsonTo<COMMAND_PCIR_TYPE>();

                if (A.COMMAND.Equals("RecogniseResult"))
                {
                    var address = (e.Session.RemoteEndPoint as IPEndPoint).Address.ToString();
                    OnFaceCardDetectionChanged?.Invoke(this, new HanvonRecivedEventArgs { IpAddress = address, Data = A.PARAM });

                    // 回送
                    var r = new Reply22(new Parma22("", "success", string.Empty, string.Empty), "RecogniseResult");
                    e.Session.Write(r.ToJsonString());
                }

                if (string.Equals(A.COMMAND, "AKE"))
                {
                    // 注意：保存数据然后进行回复
                    ServerReturnParamTpm M = new ServerReturnParamTpm();
                    ServerReturnTpm N = new ServerReturnTpm(M, "AKE");
                    e.Session.Write(M.ToJsonString());
                }
                else if (string.Equals(A.COMMAND, "GetRequest"))
                {
                    bool hasExec = false;
                    if (hasExec)
                    {
                        OnExecSync?.Invoke(this, null);
                    }

                    ServerReturnParamTpm M = new ServerReturnParamTpm();
                    ServerReturnTpm N = new ServerReturnTpm(M, "GetRequest");
                    e.Session.Write(N.ToJsonString());
                }
            }
            catch(Exception ex)
            {
                LogEx.Error("汉王服务端接收", ex);
            }
        }

        #endregion

        #region Start

        /// <summary>
        /// 服务开始运行
        /// </summary>
        public void Start()
        {
            if (IsServerRunning) return;

            try
            {
                // 开启侦听TcpServer
                TcpServer = new AsyncSocketAcceptor();
                TcpServer.FilterChain.AddLast("codec", new ProtocolCodecFilter( // 参数 false 表示不强制加密
                    new FaceReaderProtocolCodecFactory(false, null)));

                // 连接建立
                TcpServer.SessionOpened += TcpServer_SessionOpened;
                TcpServer.MessageReceived += TcpServer_MessageReceived;

                TcpServer.ExceptionCaught += TcpServer_ExceptionCaught;

                // 绑定侦听端口，开始侦听
                TcpServer.Bind(new IPEndPoint(IPAddress.Parse("0.0.0.0"), _tcpPort));

                IsServerRunning = true;

                IPEndPoint localIpep = new IPEndPoint(IPAddress.Parse("0.0.0.0"), _udpPort); // 本机IP和监听端口号
                udpcRecv = new UdpClient(localIpep);
                Thread thrRecv = new Thread(ReceiveMessage);
                thrRecv.Start();
            }
            catch(Exception ex)
            {
                LogEx.Error("汉王服务端接收启动", ex);
            }
        }

        #endregion

        private UdpClient udpcRecv = null;

        private void ReceiveMessage(object obj)
        {
            IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Any, 0);
            while (IsServerRunning)
            {
                try
                {
                    byte[] bytRecv = udpcRecv.Receive(ref remoteIpep);
                    string message = System.Text.Encoding.UTF8.GetString(bytRecv);

                    //IPAddress HostIP = IPAddress.Parse("192.168.138.23");//这个是前端设备的IP地址
                    //IPEndPoint host = new IPEndPoint(HostIP, ((IPEndPoint)remoteIpep).Port);
                    ServerReturnDevStatusParamTpm M = new ServerReturnDevStatusParamTpm();
                    ServerReturnDevStatusTpm N = new ServerReturnDevStatusTpm(M, "DevStatus");
                    byte[] sendbytes = System.Text.Encoding.UTF8.GetBytes(N.ToJsonString());

                    udpcRecv.Send(sendbytes, sendbytes.Length, remoteIpep);
                }
                catch (Exception ex)
                {
                    LogEx.Error("汉王服务端接收消息", ex);
                }
            }
        }

        #region Stop

        /// <summary>
        /// 服务停止运行
        /// </summary>
        public void Stop()
        {
            if (!IsServerRunning) return;

            // 停止侦听
            if (TcpServer != null)
            {
                TcpServer.Dispose();
                TcpServer = null;
            }

            IsServerRunning = false;
        }

        #endregion
    }
}